隨著網站的功能擴充,越來越多支的 Amazon Lambda Function 的出現,管理上變得有些複雜。 除了 Lambda 本身的 Source Code 外,還有各個 Lambda Function 使用的 IAM Roles / Policies 分別設定了不同的權限並允許各自可以觸及的範圍。 除此之外,一些在等待 DynamoDB 存取的程式,需要運行比較長的秒數,也有對應的設定喔。
Terraform
brew install terraform
aws cli 已經可以正常運作 / 或者是初始化設定 credentialsaws configure
aws sts get-caller-identity
HashiCorp Terraform 套件,以利後續管理原始碼。vlog-infra/
 ├── main.tf
 ├── variables.tf
 ├── outputs.tf
 ├── lambda/
 │   ├── list_vlog_videos/
 │   │   ├── main.py
 │   │   └── requirements.txt
 │   ├── register_vlog_member/
 │   │   ├── main.py
 │   │   └── requirements.txt
 │   └── ...
main.tfmain.tf,用來描述我們的基礎設施,集中收納 AWS 上的一些通用資源。terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
  required_version = ">= 1.5.0"
}
provider "aws" {
  region = "ap-northeast-1"
}
# 🔹 IAM Role for Lambda
resource "aws_iam_role" "lambda_exec" {
  name = "lambda-execution-role"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect = "Allow"
      Principal = { Service = "lambda.amazonaws.com" }
      Action = "sts:AssumeRole"
    }]
  })
}
# 🔹 IAM Policy 附加 (讓 Lambda 能使用 S3 / DynamoDB / SES)
resource "aws_iam_role_policy" "lambda_policy" {
  name = "lambda-execution-policy"
  role = aws_iam_role.lambda_exec.id
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Action = [
          "logs:*",
          "s3:*",
          "dynamodb:*",
          "ses:SendEmail"
        ],
        Resource = "*"
      }
    ]
  })
}
# 🔹 Lambda Function (list-vlog-videos)
resource "aws_lambda_function" "list_vlog_videos" {
  function_name = "list-vlog-videos"
  role          = aws_iam_role.lambda_exec.arn
  handler       = "main.lambda_handler"
  runtime       = "python3.13"
  filename         = "lambda/list_vlog_videos.zip"
  source_code_hash = filebase64sha256("lambda/list_vlog_videos.zip")
  environment {
    variables = {
      BUCKET_NAME = "exsky-backup-media"
      JWT_SECRET  = "mysecret"
    }
  }
}
# 🔹 API Gateway (HTTP API)
resource "aws_apigatewayv2_api" "vlog_api" {
  name          = "vlog-api"
  protocol_type = "HTTP"
}
# 🔹 Lambda Integration
resource "aws_apigatewayv2_integration" "list_videos_integration" {
  api_id                 = aws_apigatewayv2_api.vlog_api.id
  integration_type       = "AWS_PROXY"
  integration_uri        = aws_lambda_function.list_vlog_videos.invoke_arn
  payload_format_version = "2.0"
}
# 🔹 路由 (GET /list-videos)
resource "aws_apigatewayv2_route" "list_videos_route" {
  api_id    = aws_apigatewayv2_api.vlog_api.id
  route_key = "GET /list-videos"
  target    = "integrations/${aws_apigatewayv2_integration.list_videos_integration.id}"
}
# 🔹 API 部署
resource "aws_apigatewayv2_stage" "prod" {
  api_id      = aws_apigatewayv2_api.vlog_api.id
  name        = "prod"
  auto_deploy = true
}
# 🔹 允許 API Gateway 呼叫 Lambda
resource "aws_lambda_permission" "apigw_invoke" {
  statement_id  = "AllowAPIGatewayInvoke"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.list_vlog_videos.function_name
  principal     = "apigateway.amazonaws.com"
  source_arn    = "${aws_apigatewayv2_api.vlog_api.execution_arn}/*/*"
}
output "api_endpoint" {
  value = aws_apigatewayv2_stage.prod.invoke_url
}
Download / Download function code .zip
deployment package (.zip)
mkdir -p lambda
cd lambda
# 把所有的 Vlog 相關的 Function 都載下來,這邊用一支 list-vlog-videos 當作範例
aws lambda get-function --function-name list-vlog-videos --query 'Code.Location' --output text | xargs curl -o list-vlog-videos.zip
# 其他還有 ... (截至今日,共 14 支)
reset-vlog-password
forgot-vlog-password
register-vlog-member
verify-vlog-email
generate-vlog-cover
prompt-vlog-reel
generate-vlog-subtitle
delete-vlog-video
convert-vlog-mov-to-mp4
list-vlog-subtitles
generate-vlog-s3-presigned-url
validate-vlog-member
login-vlog-member
lambda 目錄專門收容各個 Lambda。# 🔹 Lambda Function (list-vlog-videos)
resource "aws_lambda_function" "list_vlog_videos" {
  function_name = "list-vlog-videos"
  role          = aws_iam_role.lambda_exec.arn
  handler       = "main.lambda_handler"
  runtime       = "python3.13"
  filename         = "lambda/list_vlog_videos.zip"
  source_code_hash = filebase64sha256("lambda/list_vlog_videos.zip")
  environment {
    variables = {
      BUCKET_NAME = "exsky-backup-media"
      JWT_SECRET  = "mysecret"
    }
  }
}
filename         = "lambda/list_vlog_videos.zip"
terraform init
terraform plan
terraform apply